--- tre-python.c	2009-09-19 07:38:42.000000000 -0700
+++ /home/ben/Downloads/tre-python.c	2018-03-15 23:32:07.540064053 -0700
@@ -86,9 +86,9 @@
   TreFuzzynessObject *self = (TreFuzzynessObject*)obj;
   PyObject *o;
 
-  o = PyString_FromFormat("%s(delcost=%d,inscost=%d,maxcost=%d,subcost=%d,"
+  o = PyUnicode_FromFormat("%s(delcost=%d,inscost=%d,maxcost=%d,subcost=%d,"
 			  "maxdel=%d,maxerr=%d,maxins=%d,maxsub=%d)",
-			  self->ob_type->tp_name, self->ap.cost_del,
+			  Py_TYPE(self)->tp_name, self->ap.cost_del,
 			  self->ap.cost_ins, self->ap.max_cost,
 			  self->ap.cost_subst, self->ap.max_del,
 			  self->ap.max_err, self->ap.max_ins,
@@ -118,8 +118,7 @@
 };
 
 static PyTypeObject TreFuzzynessType = {
-  PyObject_HEAD_INIT(NULL)
-  0,			        /* ob_size */
+  PyVarObject_HEAD_INIT(NULL, 0)
   TRE_MODULE ".Fuzzyness",	/* tp_name */
   sizeof(TreFuzzynessObject),	/* tp_basicsize */
   0,			        /* tp_itemsize */
@@ -193,7 +192,7 @@
 }
 
 static PyObject *
-PyTreMatch_groupi(PyObject *obj, int gn)
+PyTreMatch_groupi(PyObject *obj, Py_ssize_t gn)
 {
   TreMatchObject *self = (TreMatchObject*)obj;
   PyObject *result;
@@ -220,7 +219,7 @@
   PyObject *result;
   long gn;
 
-  gn = PyInt_AsLong(grpno);
+  gn = PyLong_AsLong(grpno);
 
   if (PyErr_Occurred())
     return NULL;
@@ -277,8 +276,7 @@
 };
 
 static PyTypeObject TreMatchType = {
-  PyObject_HEAD_INIT(NULL)
-  0,			        /* ob_size */
+  PyVarObject_HEAD_INIT(NULL, 0)
   TRE_MODULE ".Match",		/* tp_name */
   sizeof(TreMatchObject),	/* tp_basicsize */
   0,			        /* tp_itemsize */
@@ -337,9 +335,18 @@
   char *targ;
   size_t tlen;
 
-  if (!PyArg_ParseTuple(args, "SO!|i:match", &pstring, &TreFuzzynessType,
+  if (PyTuple_Size(args) > 0 && PyUnicode_Check(PyTuple_GetItem(args, 0)))
+    {
+      if (!PyArg_ParseTuple(args, "UO!|i:search", &pstring, &TreFuzzynessType,
 			&fz, &eflags))
-    return NULL;
+      return NULL;
+    }
+  else
+    {
+      if (!PyArg_ParseTuple(args, "SO!|i:search", &pstring, &TreFuzzynessType,
+			&fz, &eflags))
+      return NULL;
+    }
 
   mo = newTreMatchObject();
   if (mo == NULL)
@@ -347,22 +354,35 @@
 
   nsub = self->rgx.re_nsub + 1;
   pm = PyMem_New(regmatch_t, nsub);
-  if (pm != NULL)
-    {
-      mo->am.nmatch = nsub;
-      mo->am.pmatch = pm;
-    }
-  else
+  if (!pm)
     {
-      /* XXX */
       Py_DECREF(mo);
-      return NULL;
+      return PyErr_NoMemory();
     }
 
-  targ = PyString_AsString(pstring);
-  tlen = PyString_Size(pstring);
+  mo->am.nmatch = nsub;
+  mo->am.pmatch = pm;
 
-  rc = tre_reganexec(&self->rgx, targ, tlen, &mo->am, fz->ap, eflags);
+  if (PyUnicode_Check(pstring))
+    {
+      Py_ssize_t len = PyUnicode_GetSize(pstring);
+      wchar_t *buf = calloc(sizeof(wchar_t), len);
+      if(!buf)
+        {
+          Py_DECREF(mo);
+          return PyErr_NoMemory();
+        }
+      PyUnicode_AsWideChar(pstring, buf, len);
+      rc = tre_regawnexec(&self->rgx, buf, len, &mo->am, fz->ap, eflags);
+      free(buf);
+    }
+  else
+    {
+      targ = PyBytes_AsString(pstring);
+      tlen = PyBytes_Size(pstring);
+
+      rc = tre_reganexec(&self->rgx, targ, tlen, &mo->am, fz->ap, eflags);
+    }
 
   if (PyErr_Occurred())
     {
@@ -392,7 +412,7 @@
 
 static PyMethodDef TrePattern_methods[] = {
   { "search", (PyCFunction)PyTrePattern_search, METH_VARARGS,
-    "try to match against given string, returning " TRE_MODULE ".match object "
+    "try to search in the given string, returning " TRE_MODULE ".match object "
     "or None on failure" },
   {NULL, NULL}
 };
@@ -411,8 +431,7 @@
 }
 
 static PyTypeObject TrePatternType = {
-  PyObject_HEAD_INIT(NULL)
-  0,			        /* ob_size */
+  PyVarObject_HEAD_INIT(NULL, 0)
   TRE_MODULE ".Pattern",	/* tp_name */
   sizeof(TrePatternObject),	/* tp_basicsize */
   0,			        /* tp_itemsize */
@@ -445,7 +464,7 @@
 };
 
 static TrePatternObject *
-newTrePatternObject(PyObject *args)
+newTrePatternObject(void)
 {
   TrePatternObject *self;
 
@@ -460,19 +479,43 @@
 PyTre_ncompile(PyObject *self, PyObject *args)
 {
   TrePatternObject *rv;
-  char *pattern;
+  PyObject *upattern = NULL;
+  char *pattern = NULL;
   int pattlen;
   int cflags = 0;
   int rc;
 
-  if (!PyArg_ParseTuple(args, "s#|i:compile", &pattern, &pattlen, &cflags))
-    return NULL;
+  if (PyTuple_Size(args) > 0 && PyUnicode_Check(PyTuple_GetItem(args, 0)))
+    {
+      if (!PyArg_ParseTuple(args, "U|i:compile", &upattern, &cflags))
+        return NULL;
+    }
+  else
+    {
+      if (!PyArg_ParseTuple(args, "s#|i:compile", &pattern, &pattlen, &cflags))
+        return NULL;
+    }
 
-  rv = newTrePatternObject(args);
+  rv = newTrePatternObject();
   if (rv == NULL)
     return NULL;
 
-  rc = tre_regncomp(&rv->rgx, (char*)pattern, pattlen, cflags);
+  if (upattern != NULL)
+    {
+      Py_ssize_t len = PyUnicode_GetSize(upattern);
+      wchar_t *buf = calloc(sizeof(wchar_t), len);
+      if(!buf)
+        {
+          Py_DECREF(rv);
+          return PyErr_NoMemory();
+        }
+      PyUnicode_AsWideChar(upattern, buf, len);
+      rc = tre_regwncomp(&rv->rgx, buf, len, cflags);
+      free(buf);
+    }
+  else
+    rc = tre_regncomp(&rv->rgx, (char*)pattern, pattlen, cflags);
+
   if (rc != REG_OK)
     {
       if (!PyErr_Occurred())
@@ -491,9 +534,8 @@
   { NULL, NULL }
 };
 
-static char *tre_doc =
-"Python module for TRE library\n\nModule exports "
-"the only function: compile";
+
+#define tre_doc "Python module for TRE library\n\nModule exports the only function: compile"
 
 static struct _tre_flags {
   char *name;
@@ -510,40 +552,57 @@
   { NULL, 0 }
 };
 
+
+static struct PyModuleDef moduledef = {
+  PyModuleDef_HEAD_INIT,
+  TRE_MODULE ".Module",   /* m_name */
+  tre_doc,             /* m_doc */
+  -1,                  /* m_size */
+  tre_methods,         /* m_methods */
+  NULL,                /* m_reload */
+  NULL,                /* m_traverse */
+  NULL,                /* m_clear */
+  NULL,                /* m_free */
+};
+
+
 PyMODINIT_FUNC
-inittre(void)
+PyInit_tre(void)
 {
   PyObject *m;
   struct _tre_flags *fp;
 
   if (PyType_Ready(&TreFuzzynessType) < 0)
-    return;
+    return NULL;
   if (PyType_Ready(&TreMatchType) < 0)
-    return;
+    return NULL;
   if (PyType_Ready(&TrePatternType) < 0)
-    return;
+    return NULL;
 
   /* Create the module and add the functions */
-  m = Py_InitModule3(TRE_MODULE, tre_methods, tre_doc);
+
+  m = PyModule_Create (&moduledef);
+
   if (m == NULL)
-    return;
+    return NULL;
 
   Py_INCREF(&TreFuzzynessType);
   if (PyModule_AddObject(m, "Fuzzyness", (PyObject*)&TreFuzzynessType) < 0)
-    return;
+    return NULL;
   Py_INCREF(&TreMatchType);
   if (PyModule_AddObject(m, "Match", (PyObject*)&TreMatchType) < 0)
-    return;
+    return NULL;
   Py_INCREF(&TrePatternType);
   if (PyModule_AddObject(m, "Pattern", (PyObject*)&TrePatternType) < 0)
-    return;
+    return NULL;
   ErrorObject = PyErr_NewException(TRE_MODULE ".Error", NULL, NULL);
   Py_INCREF(ErrorObject);
   if (PyModule_AddObject(m, "Error", ErrorObject) < 0)
-    return;
+    return NULL;
 
   /* Insert the flags */
   for (fp = tre_flags; fp->name != NULL; fp++)
     if (PyModule_AddIntConstant(m, fp->name, fp->val) < 0)
-      return;
+      return NULL;
+  return m;
 }
